#ifndef ZL_COLLECTION_INTERFACES
#define ZL_COLLECTION_INTERFACES

#include <iterator>
#include <memory>
#include "../Basic/Basic.h"
#include "Pair.h"

namespace zl
{
	namespace collections
	{

		template<typename T>
		class Iterator
		{
			typedef Iterator<T>                      Tself;
		public:
			typedef std::random_access_iterator_tag  iterator_category;
			typedef T                                value_type;
			typedef zint                             difference_type;
			typedef T*                               pointer;
			typedef T&                               reference;
		private:
			pointer                                  iterator;
		public:
			Iterator() :iterator(nullptr)
			{}

			Iterator(const pointer& _iterator) :iterator(_iterator)
			{
			}

			Tself&      operator++()
			{
				iterator++;
				return *this;
			}

			Tself       operator++(int)
			{
				Tself t = *this;
				iterator++;
				return t;
			}

			Tself&        operator--()
			{
				iterator--;
				return *this;
			}

			Tself          operator--(int)
			{
				Tself t = *this;
				iterator--;
				return t;
			}

			reference         operator[](difference_type off)const
			{
				return (*(this + off));
			}

			reference         operator*()const
			{
				return *iterator;
			}

			pointer            operator->()const
			{
				return iterator;
			}

			Tself&      operator+=(difference_type off)
			{
				iterator += off;
				return *this;
			}

			Tself&      operator-=(difference_type off)
			{
				iterator += -off;
				return *this;
			}

			Tself       operator+(difference_type off)const
			{
				Tself t = *this;
				return (t += off);
			}

			Tself       operator-(difference_type off)const
			{
				Tself t = *this;
				return (t -= off);
			}

			difference_type operator-(const Tself& it)const
			{
				return iterator - it.iterator;
			}

			bool        operator==(const Tself& it)const
			{
				return iterator == it.iterator;
			}

			bool        operator!=(const Tself& it)const
			{
				return iterator != it.iterator;
			}

			bool        operator>(const Tself& it)const
			{
				return iterator > (it.iterator);
			}
			
			bool        operator>=(const Tself& it)const
			{
				return iterator >= (it.iterator);
			}

			bool        operator<(const Tself& it)const
			{
				return iterator < (it.iterator);
			}

			bool       operator<=(const Tself& it)const
			{
				return iterator <= (it.iterator);
			}

			void        swap(Tself& right)
			{
				T tmp = *iterator;
				*iterator = *(right.iterator);
				*(right.iterator) = std::move(tmp);
			}

			pointer      obj()const
			{
				return iterator;
			}
		};

		template<typename K, typename V>
		class PairIterator
		{
			typedef PairIterator<K, V>               Tself;
		public:
			typedef std::random_access_iterator_tag  iterator_category;
			typedef Pair<K, V>                       value_type;
			typedef zint                             difference_type;
			typedef value_type*                      pointer;
			typedef value_type&                      reference;
		private:
			Iterator<K>                              iterator1;
			Iterator<V>                              iterator2;
		public:
			PairIterator() :iterator1(nullptr), iterator2(nullptr)
			{

			}

			PairIterator(const Iterator<K>& _iterator1,const Iterator<V>& _iterator2):
				iterator1(_iterator1), iterator2(_iterator2)
			{
				
			}

			Tself&      operator++()
			{
				iterator1++;
				iterator2++;
				return *this;
			}

			Tself       operator++(int)
			{
				Tself t = *this;
				iterator1++;
				iterator2++;
				return t;
			}

			Tself&        operator--()
			{
				iterator1--;
				iterator2--;
				return *this;
			}

			Tself          operator--(int)
			{
				Tself t = *this;
				iterator1--;
				iterator2--;
				return t;
			}

			value_type         operator[](difference_type off)const
			{
				return (*(this + off));
			}

			value_type         operator*()const
			{
				return value_type(*iterator1,*iterator2);
			}

			Tself&      operator+=(difference_type off)
			{
				iterator1 += off;
				iterator2 += off;
				return *this;
			}

			Tself&      operator-=(difference_type off)
			{
				iterator1 += -off;
				iterator2 += -off;
				return *this;
			}

			Tself       operator+(difference_type off)const
			{
				Tself t = *this;
				return (t += off);
			}

			Tself       operator-(difference_type off)const
			{
				Tself t = *this;
				return (t -= off);
			}

			Iterator<K>    obj1()const
			{
				return iterator1;
			}

			Iterator<V>    obj2()const
			{
				return iterator2;
			}

			difference_type operator-(const Tself& it)const
			{
				return iterator1 - it.iterator1;
			}

			bool        operator==(const Tself& it)const
			{
				return iterator1 == it.iterator1 && it.iterator2==iterator2;
			}

			bool        operator!=(const Tself& it)const
			{
				return iterator1 != it.iterator1 && it.iterator2!=iterator2;
			}

			bool        operator>(const Tself& it)const
			{
				return iterator1 > (it.iterator1) && iterator2 > (it.iterator1);
			}

			bool        operator>=(const Tself& it)const
			{
				return iterator1 >= (it.iterator1) && iterator2 > (it.iterator2);
			}

			bool        operator<(const Tself& it)const
			{
				return iterator1 < (it.iterator1) && iterator2 < (it.iterator2);
			}

			bool       operator<=(const Tself& it)const
			{
				return iterator1 <= (it.iterator1) && iterator2 <= (it.iterator2);
			}
		};
	};
};
#endif